#ifndef MEMORY_MANGMENT_H
#define MEMORY_MANGMENT_H
#include "stdint.h"


#ifndef CPU_INT08U
typedef  unsigned  char                 CPU_INT08U;           /*  8-bit unsigned integer  */
#endif

#ifndef CPU_INT32U
typedef  uint32_t                       CPU_INT32U;           /* 32-bit unsigned integer  */
#endif

#ifndef CPU_SIZE
typedef  size_t                          CPU_SIZE;           /* 32-bit unsigned integer  */
typedef  CPU_SIZE                        CPU_DATA;
typedef  CPU_SIZE                        CPU_ADDR;
#endif


//os_mem 成员变量类型
typedef   uint32_t                      OS_OBJ_TYPE; 
typedef   char                          CPU_CHAR;
typedef   uint16_t                      OS_MEM_QTY;                  /* Number of memory blocks,   <16>/32 */
typedef   uint16_t                      OS_MEM_SIZE;                 /* Size in bytes of a memory block,  */             
typedef   struct  os_mem                OS_MEM;

struct os_mem {                                             /* MEMORY CONTROL BLOCK                                   */
    OS_OBJ_TYPE          Type;                              /* Should be set to OS_OBJ_TYPE_MEM                       */
    void                *AddrPtr;                           /* Pointer to beginning of memory partition               */
    CPU_CHAR            *NamePtr;
    void                *FreeListPtr;                       /* Pointer to list of free memory blocks                  */
    OS_MEM_SIZE          BlkSize;                           /* Size (in bytes) of each block of memory                */
    OS_MEM_QTY           NbrMax;                            /* Total number of blocks in this partition               */
    OS_MEM_QTY           NbrFree;                           /* Number of memory blocks remaining in this partition    */
#if OS_CFG_DBG_EN > 0u
    OS_MEM              *DbgPrevPtr;
    OS_MEM              *DbgNextPtr;
#endif
};


typedef  enum  os_mem_err {
    OS_ERR_NONE                      =     0u,

    OS_ERR_MEM_CREATE_ISR            = 22201u,
    OS_ERR_MEM_FULL                  = 22202u,
    OS_ERR_MEM_INVALID_P_ADDR        = 22203u,
    OS_ERR_MEM_INVALID_BLKS          = 22204u,
    OS_ERR_MEM_INVALID_PART          = 22205u,
    OS_ERR_MEM_INVALID_P_BLK         = 22206u,
    OS_ERR_MEM_INVALID_P_MEM         = 22207u,
    OS_ERR_MEM_INVALID_P_DATA        = 22208u,
    OS_ERR_MEM_INVALID_SIZE          = 22209u,
    OS_ERR_MEM_NO_FREE_BLKS          = 22210u,

} OS_MEM_ERR;



/**
 * @brief 创建一个内存区
 * 
 * @param p_mem     指向一个内存区的指针，多为创建的二维数组，可以用malloc创建或者直接建立数组
 * @param p_name    给这个内存区起个名字
 * @param p_addr    内存区地址
 * @param n_blks    该区域的内存块数量
 * @param blk_size  每个内存块的大小
 * @param p_err     错误指针
 */
void   umem_block_create(   OS_MEM       *p_mem,
                            CPU_CHAR     *p_name,
                            void         *p_addr,
                            OS_MEM_QTY    n_blks,
                            OS_MEM_SIZE   blk_size,
                            OS_MEM_ERR       *p_err);

/**
 * @brief           从内存区里取一个内存块
 * 
 * @param p_mem     指向内存区的地址的指针
 * @param p_err     错误指针
 * @return void*    返回到一个内存块的首地址，找个指针指向这个地址
 */
void  *umem_block_malloc (  OS_MEM  *p_mem,
                            OS_MEM_ERR  *p_err);

/**
 * @brief       释放一个内存块
 * 
 * @param p_mem     指向内存区的地址的指针
 * @param p_blk     指向需要释放的内存块的那个指针
 * @param p_err     错误指针
 */
void  umem_block_free ( OS_MEM  *p_mem,
                        void    *p_blk,
                        OS_MEM_ERR  *p_err);


/**
 * @brief 获得memory中空闲的块数
 * 
 * @param memory    一块内存区域的句柄
 * @return CPU_SIZE 
 */
CPU_SIZE umem_get_free_block(OS_MEM* memory);

/**
 * @brief 获得该memory中最大块数
 * 
 * @param memory        一块内存区域的句柄
 * @return CPU_SIZE 
 */
CPU_SIZE umem_get_max_block(OS_MEM* memory);

#endif
